package grpcserver

import (
	"gitee.com/scottq/go-framework/src/utils"
	"gitee.com/scottq/go-framework/src/v1/config"
	"gitee.com/scottq/go-framework/src/v1/log"
	"google.golang.org/grpc"
	"net"
	"strings"
)

type HandlerFunc = func(*grpc.Server)

type GRPCServer struct {
	log.InvokeLog
	//名称
	name string
	//监听地址
	listenAddr   string
	s            *grpc.Server
	HandlerFunc  HandlerFunc
	handlerFuncs []HandlerFunc

	//服务注册者
	serviceRegister IServiceRegister

	conf *config.RpcServerConfig
}

func NewGRPCServer(name string, conf *config.RpcServerConfig) (*GRPCServer, error) {
	server := &GRPCServer{
		name:       name,
		listenAddr: conf.RpcLisAddr,
		s:          grpc.NewServer(),
		conf:       conf,
	}

	switch conf.RpcRegWay {
	case config.RpcRegByEtcd:
		etcd, _ := NewEtcdSrvRegister(conf.RpcRegServer)
		server.AddServiceRegister(etcd)
	}

	return server, nil
}

//add服务注册中心
func (svr *GRPCServer) AddServiceRegister(r IServiceRegister) {
	if r != nil {
		svr.serviceRegister = r
	}
}

//add服务处理handler
func (svr *GRPCServer) AddServiceHandler(f HandlerFunc) {
	funcs := svr.handlerFuncs
	if funcs == nil {
		funcs = []HandlerFunc{}
	}
	if f != nil {
		funcs = append(funcs, f)
	}
	svr.handlerFuncs = funcs
}

func (svr *GRPCServer) Run() error {
	//向注册中心注册服务
	err := svr.registerService()
	if err != nil {
		return err
	}

	//启动
	return svr.run()
}

func (svr *GRPCServer) run() error {
	lis, err := net.Listen("tcp", svr.listenAddr)
	if err != nil {
		svr.Fatal("failed to listen: %v", err)
	}

	//服务方法处理者方法
	if svr.HandlerFunc != nil {
		svr.HandlerFunc(svr.s)
	}

	//多个服务注册
	if funcs := svr.handlerFuncs; svr.handlerFuncs != nil && len(svr.handlerFuncs) > 0 {
		for _, f := range funcs {
			f(svr.s)
		}
	}

	svr.Info("[%s]rpc running at %s", svr.name, svr.listenAddr)
	if err := svr.s.Serve(lis); err != nil {
		svr.Fatal("failed to serve: %v", err)
		return err
	}

	return nil
}

func (svr *GRPCServer) registerService() error {
	regServer := svr.conf.RpcRequestAddr

	if regServer == "" {
		RequestIp, err := utils.GetLocalIP()
		if err != nil {
			return err
		}
		RequestPort := strings.Split(svr.listenAddr, ":")[1]
		regServer = RequestIp + ":" + RequestPort
	}

	if svr.serviceRegister != nil {
		svr.Info("[%s]rpc register addr %s", svr.name, regServer)
		return svr.serviceRegister.Register(svr.name, regServer)
	}

	return nil
}
